using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.DependencyInjection;

namespace CKY.AgentPlatform.Caching
{
    /// <summary>
    /// 响应缓存特性
    /// </summary>
    public class ResponseCacheAttribute : Attribute, IAsyncActionFilter, ITransientDependency
    {
        private readonly DistributedCacheService _cacheService;
        private readonly ILogger<ResponseCacheAttribute> _logger;

        public int Duration { get; set; } = 300; // 默认5分钟
        public string CacheKeyPrefix { get; set; }
        public bool VaryByUser { get; set; } = false;
        public bool VaryByQuery { get; set; } = false;
        public string[] VaryByHeader { get; set; }
        public bool IgnoreAuthenticated { get; set; } = false;

        public ResponseCacheAttribute()
        {
        }

        public ResponseCacheAttribute(int duration)
        {
            Duration = duration;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 获取服务
            _cacheService = context.HttpContext.RequestServices.GetService<DistributedCacheService>();
            _logger = context.HttpContext.RequestServices.GetService<ILogger<ResponseCacheAttribute>>();

            if (_cacheService == null)
            {
                await next();
                return;
            }

            // 检查是否应该缓存
            if (ShouldSkipCache(context))
            {
                await next();
                return;
            }

            // 生成缓存键
            var cacheKey = GenerateCacheKey(context);
            
            // 尝试从缓存获取
            var cachedResponse = await _cacheService.GetAsync<CachedResponse>(cacheKey);
            if (cachedResponse != null)
            {
                _logger.LogDebug("响应缓存命中: {CacheKey}", cacheKey);
                
                var result = new ContentResult
                {
                    Content = cachedResponse.Content,
                    ContentType = cachedResponse.ContentType,
                    StatusCode = cachedResponse.StatusCode
                };

                foreach (var header in cachedResponse.Headers)
                {
                    context.HttpContext.Response.Headers[header.Key] = header.Value;
                }

                context.Result = result;
                return;
            }

            // 执行原始方法
            var resultContext = await next();
            var result = resultContext.Result;

            // 缓存响应
            if (result != null && CanCacheResult(result))
            {
                await CacheResponseAsync(context, result, cacheKey);
            }
        }

        private bool ShouldSkipCache(ActionExecutingContext context)
        {
            // 跳过非GET请求
            if (!HttpMethods.IsGet(context.HttpContext.Request.Method))
            {
                return true;
            }

            // 如果配置为跳过已认证用户
            if (IgnoreAuthenticated && context.HttpContext.User.Identity.IsAuthenticated)
            {
                return true;
            }

            // 跳过带有特定头的请求
            if (context.HttpContext.Request.Headers.ContainsKey("Cache-Control") && 
                context.HttpContext.Request.Headers["Cache-Control"].ToString().Contains("no-cache"))
            {
                return true;
            }

            return false;
        }

        private string GenerateCacheKey(ActionExecutingContext context)
        {
            var keyParts = new System.Collections.Generic.List<string>();

            // 前缀
            if (!string.IsNullOrEmpty(CacheKeyPrefix))
            {
                keyParts.Add(CacheKeyPrefix);
            }
            else
            {
                keyParts.Add("Response");
            }

            // 路由信息
            var controller = context.Controller.GetType().Name.Replace("Controller", "");
            var action = context.ActionDescriptor.RouteValues["action"];
            keyParts.Add($"{controller}.{action}");

            // 路由参数
            foreach (var param in context.ActionArguments)
            {
                keyParts.Add($"{param.Key}={param.Value}");
            }

            // 查询参数
            if (VaryByQuery)
            {
                var queryString = context.HttpContext.Request.QueryString.ToString();
                if (!string.IsNullOrEmpty(queryString))
                {
                    keyParts.Add($"query={queryString}");
                }
            }

            // 用户信息
            if (VaryByUser)
            {
                var userId = context.HttpContext.User?.Identity?.Name ?? "anonymous";
                keyParts.Add($"user={userId}");
            }

            // 请求头
            if (VaryByHeader != null && VaryByHeader.Any())
            {
                foreach (var header in VaryByHeader)
                {
                    if (context.HttpContext.Request.Headers.TryGetValue(header, out var values))
                    {
                        keyParts.Add($"{header}={values}");
                    }
                }
            }

            return string.Join(":", keyParts);
        }

        private bool CanCacheResult(IActionResult result)
        {
            return result switch
            {
                OkResult => true,
                ObjectResult objectResult when objectResult.StatusCode >= 200 && objectResult.StatusCode < 300 => true,
                ContentResult contentResult when contentResult.StatusCode >= 200 && contentResult.StatusCode < 300 => true,
                JsonResult jsonResult when jsonResult.StatusCode >= 200 && jsonResult.StatusCode < 300 => true,
                _ => false
            };
        }

        private async Task CacheResponseAsync(ActionExecutingContext context, IActionResult result, string cacheKey)
        {
            try
            {
                var cachedResponse = new CachedResponse();

                // 处理不同类型的响应
                switch (result)
                {
                    case ContentResult contentResult:
                        cachedResponse.Content = contentResult.Content;
                        cachedResponse.ContentType = contentResult.ContentType;
                        cachedResponse.StatusCode = contentResult.StatusCode;
                        break;
                        
                    case ObjectResult objectResult:
                        cachedResponse.Content = System.Text.Json.JsonSerializer.Serialize(objectResult.Value);
                        cachedResponse.ContentType = "application/json";
                        cachedResponse.StatusCode = objectResult.StatusCode;
                        break;
                        
                    case JsonResult jsonResult:
                        cachedResponse.Content = System.Text.Json.JsonSerializer.Serialize(jsonResult.Value);
                        cachedResponse.ContentType = "application/json";
                        cachedResponse.StatusCode = jsonResult.StatusCode;
                        break;
                        
                    default:
                        return; // 不缓存其他类型的响应
                }

                // 保存响应头
                cachedResponse.Headers = new System.Collections.Generic.Dictionary<string, string>();
                foreach (var header in context.HttpContext.Response.Headers)
                {
                    if (!header.Key.StartsWith("X-")) // 只保存非自定义头
                    {
                        cachedResponse.Headers[header.Key] = header.Value;
                    }
                }

                // 缓存响应
                await _cacheService.SetAsync(cacheKey, cachedResponse, TimeSpan.FromSeconds(Duration));
                
                // 添加缓存头
                context.HttpContext.Response.Headers["X-Cache-Key"] = cacheKey;
                context.HttpContext.Response.Headers["X-Cache-Duration"] = Duration.ToString();
                
                _logger.LogDebug("响应缓存设置: {CacheKey}, 时长: {Duration}s", cacheKey, Duration);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存响应失败: {CacheKey}", cacheKey);
            }
        }
    }

    /// <summary>
    /// 缓存响应数据
    /// </summary>
    public class CachedResponse
    {
        public string Content { get; set; }
        public string ContentType { get; set; }
        public int? StatusCode { get; set; }
        public System.Collections.Generic.Dictionary<string, string> Headers { get; set; }
    }

    /// <summary>
    /// 清除缓存特性
    /// </summary>
    public class ClearCacheAttribute : Attribute, IAsyncActionFilter, ITransientDependency
    {
        private readonly DistributedCacheService _cacheService;
        private readonly ILogger<ClearCacheAttribute> _logger;

        public string CacheKeyPrefix { get; set; }
        public bool ClearAll { get; set; } = false;

        public ClearCacheAttribute()
        {
        }

        public ClearCacheAttribute(string cacheKeyPrefix)
        {
            CacheKeyPrefix = cacheKeyPrefix;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 获取服务
            _cacheService = context.HttpContext.RequestServices.GetService<DistributedCacheService>();
            _logger = context.HttpContext.RequestServices.GetService<ILogger<ClearCacheAttribute>>();

            // 执行原始方法
            await next();

            // 清除缓存
            if (_cacheService != null)
            {
                await ClearCacheAsync(context);
            }
        }

        private async Task ClearCacheAsync(ActionExecutingContext context)
        {
            try
            {
                if (ClearAll)
                {
                    await _cacheService.ClearAllAsync();
                    _logger.LogInformation("清除所有缓存");
                }
                else if (!string.IsNullOrEmpty(CacheKeyPrefix))
                {
                    // 清除指定前缀的缓存
                    await _cacheService.RemoveAsync(CacheKeyPrefix);
                    _logger.LogInformation("清除缓存前缀: {CacheKeyPrefix}", CacheKeyPrefix);
                }
                else
                {
                    // 基于控制器和动作生成缓存键
                    var controller = context.Controller.GetType().Name.Replace("Controller", "");
                    var action = context.ActionDescriptor.RouteValues["action"];
                    var cacheKey = $"{controller}.{action}";
                    
                    await _cacheService.RemoveAsync(cacheKey);
                    _logger.LogInformation("清除缓存: {CacheKey}", cacheKey);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清除缓存失败");
            }
        }
    }

    /// <summary>
    /// 缓存中间件
    /// </summary>
    public class CacheMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly DistributedCacheService _cacheService;
        private readonly ILogger<CacheMiddleware> _logger;

        public CacheMiddleware(
            RequestDelegate next,
            DistributedCacheService cacheService,
            ILogger<CacheMiddleware> logger)
        {
            _next = next;
            _cacheService = cacheService;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            // 跳过非GET请求
            if (!HttpMethods.IsGet(context.Request.Method))
            {
                await _next(context);
                return;
            }

            // 生成缓存键
            var cacheKey = GenerateCacheKey(context);
            
            // 尝试从缓存获取
            var cachedResponse = await _cacheService.GetAsync<CachedResponse>(cacheKey);
            if (cachedResponse != null)
            {
                _logger.LogDebug("中间件缓存命中: {CacheKey}", cacheKey);
                
                context.Response.StatusCode = cachedResponse.StatusCode ?? 200;
                context.Response.ContentType = cachedResponse.ContentType;
                
                foreach (var header in cachedResponse.Headers)
                {
                    context.Response.Headers[header.Key] = header.Value;
                }

                await context.Response.WriteAsync(cachedResponse.Content);
                return;
            }

            // 执行后续中间件
            var originalBodyStream = context.Response.Body;
            using var responseBody = new System.IO.MemoryStream();
            context.Response.Body = responseBody;

            await _next(context);

            // 检查是否应该缓存响应
            if (context.Response.StatusCode >= 200 && context.Response.StatusCode < 300)
            {
                responseBody.Seek(0, System.IO.SeekOrigin.Begin);
                var content = await new System.IO.StreamReader(responseBody).ReadToEndAsync();
                
                var response = new CachedResponse
                {
                    Content = content,
                    ContentType = context.Response.ContentType,
                    StatusCode = context.Response.StatusCode,
                    Headers = context.Response.Headers.ToDictionary(h => h.Key, h => h.Value.ToString())
                };

                await _cacheService.SetAsync(cacheKey, response, TimeSpan.FromMinutes(5));
                
                _logger.LogDebug("中间件缓存设置: {CacheKey}", cacheKey);
            }

            responseBody.Seek(0, System.IO.SeekOrigin.Begin);
            await responseBody.CopyToAsync(originalBodyStream);
        }

        private string GenerateCacheKey(HttpContext context)
        {
            var path = context.Request.Path.ToString();
            var queryString = context.Request.QueryString.ToString();
            var method = context.Request.Method;
            
            return $"Middleware:{method}:{path}{queryString}";
        }
    }

    /// <summary>
    /// 缓存健康检查
    /// </summary>
    public class CacheHealthCheck : ITransientDependency
    {
        private readonly DistributedCacheService _cacheService;
        private readonly RedisCacheService _redisCacheService;
        private readonly ILogger<CacheHealthCheck> _logger;

        public CacheHealthCheck(
            DistributedCacheService cacheService,
            RedisCacheService redisCacheService,
            ILogger<CacheHealthCheck> logger)
        {
            _cacheService = cacheService;
            _redisCacheService = redisCacheService;
            _logger = logger;
        }

        public async Task<CacheHealthStatus> CheckHealthAsync()
        {
            var status = new CacheHealthStatus();
            
            try
            {
                // 检查分布式缓存
                var testKey = $"health_check_{DateTime.UtcNow.Ticks}";
                var testValue = "test";
                
                await _cacheService.SetAsync(testKey, testValue, TimeSpan.FromSeconds(30));
                var retrievedValue = await _cacheService.GetAsync<string>(testKey);
                
                status.DistributedCacheHealthy = retrievedValue == testValue;
                await _cacheService.RemoveAsync(testKey);
                
                // 检查Redis缓存
                if (_redisCacheService != null)
                {
                    status.RedisHealthy = await _redisCacheService.CheckHealthAsync();
                    status.RedisStatistics = await _redisCacheService.GetStatisticsAsync();
                }
                
                status.OverallHealth = status.DistributedCacheHealthy && (status.RedisHealthy ?? true);
                status.LastCheck = DateTime.UtcNow;
                
                _logger.LogInformation("缓存健康检查完成，状态: {Status}", status.OverallHealth ? "健康" : "不健康");
            }
            catch (Exception ex)
            {
                status.OverallHealth = false;
                status.ErrorMessage = ex.Message;
                _logger.LogError(ex, "缓存健康检查失败");
            }
            
            return status;
        }
    }

    /// <summary>
    /// 缓存健康状态
    /// </summary>
    public class CacheHealthStatus
    {
        public bool OverallHealth { get; set; }
        public bool DistributedCacheHealthy { get; set; }
        public bool? RedisHealthy { get; set; }
        public RedisStatistics RedisStatistics { get; set; }
        public DateTime LastCheck { get; set; }
        public string ErrorMessage { get; set; }
    }
}